#pragma once
#include<iostream>
#include<string>
#include<cassert>
#include<cstring>
#define CRLF "\r\n"
#define CRLF_LEN strlen(CRLF)
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define OPS "+-*/%"
#define BUFFER_SIZE 1024

std::string encode(const std::string& inS,uint32_t len)//encode编码
{
    std::string encodeIn=std::to_string(len);
    encodeIn += CRLF;
    encodeIn += inS;
    encodeIn += CRLF;
    return encodeIn;
}
std::string decode(std::string& inS,uint32_t* len)//decode解码
{
    assert(len);
    *len=0;
    size_t pos=inS.find(CRLF);
    if(pos==std::string::npos)
    {
        return "";
    }
    std::string inLen=inS.substr(0,pos);
    int intlen=atoi(inLen.c_str());//atoi需要以C风格的字符串作为参数

    //确认有效载荷完整，通过判断有效载荷的长度和报头给的是否一致
    int surplus=inS.size()-2*CRLF_LEN-pos;
    if(surplus<intlen)
    {
        return "";
    }

    //获取有效载荷
    std::string package=inS.substr(pos+CRLF_LEN,intlen);
    *len=intlen;

    //将完整的strPackage从原始输入字符串inBuffer中删除
    int removeLen=inLen.size()+2*CRLF_LEN+intlen;
    inS.erase(0,removeLen);

    return package;
}

//定制请求的协议
class request
{
    public:
    request(){}
    ~request(){}

    //序列化，将结构转化成字符串样的数据
    //序列化的结构：_x _op _y，即空格分割
    void serialize(std::string* out)
    {
        std::string xStr=std::to_string(get_x());
        std::string yStr=std::to_string(get_y());

        *out += xStr;
        *out += SPACE;
        *out += get_op();
        *out +=SPACE;
        *out += yStr;
    }
    bool deserialize(const std::string& in)
    {
        //根据约定好的格式先找空格
        size_t spaceOnePos=in.find(SPACE);
        if(spaceOnePos==std::string::npos)
        return false;
        size_t spaceTwoPos=in.rfind(SPACE);
        if(spaceTwoPos==std::string::npos)
        return false;
        std::string dataOne=in.substr(0,spaceOnePos);
        std::string dataTwo=in.substr(spaceTwoPos+SPACE_LEN,std::string::npos);
        std::string oper=in.substr(spaceOnePos+SPACE_LEN,spaceTwoPos);
        if(oper.size()!=1)
        return false;

        _x=atoi(dataOne.c_str());
        _y=atoi(dataTwo.c_str());
        _op=oper[0];//string到char
        return true;

    }
    int get_x() const
    {
        return _x;
    }
    int get_y() const{
        return _y;
    }
    char get_op() const{
        return _op;
    }
    void set_X(int x)
    {
        _x=x;
    }
    void set_y(int y)
    {
        _y=y;
    }
    void set_op(char op)
    {
        _op=op;
    }
    void debug(){
        std::cout<<_x<<""<<_op<<"<<_y"<<std::endl;
    }
    private:
    int _x;
    int _y;
    char _op;
};

//定制响应的协议
class response
{
    public:
        response()
            :_exitCode(0)
            ,_result(0){}
        ~response(){}
        void serialize(std::string* out)//序列化
        {
            std::string exitCode=std::to_string(_exitCode);
            std::string result=std::to_string(_result);
            *out = exitCode;
            *out = SPACE;
            *out = result;
        }
        bool deserialize(const std::string& in)
        {
            size_t posSpace=in.find(SPACE);
            if(posSpace==std::string::npos)
            {
                return false;
            }
            std::string exitCodeStr=in.substr(0,posSpace);
            std::string resultStr=in.substr(posSpace+SPACE_LEN,std::string::npos);
            _exitCode=atoi(exitCodeStr.c_str());
            _result=atoi(resultStr.c_str());
            return true;
        }
        void set_exitCode(int exitCode){
            _exitCode=exitCode;
        }
        void set_result(int result)
        {
            _result=result;
        }
        int get_exitCode()
        {
            return _exitCode;
        }
        int get_result()
        {
            return _result;
        }
        void debug()
        {
            std::cout<<_exitCode<<""<<_result<<std::endl;
        }
    public:
        int _exitCode;
        int _result;
};

bool makeRequest(const std::string& message,request* req)//定制请求
{
    //首先消除指令消息中的空格
    std::string tmpMsg;
    std::string opStr=OPS;
    for(auto e:message)
        if((e<='9'&&e>='0')||(std::string::npos!=opStr.find(e)))
        {
            tmpMsg +=e;
        }
        else if(e!=' '){
            return false;
        }
        std::cout<<tmpMsg<<std::endl;
        int opPos=0;
        int first_pos=tmpMsg.find_first_of(opStr);
        int last_pos=tmpMsg.find_last_of(opStr);

        if((tmpMsg[last_pos]!='-'&&tmpMsg[last_pos]!='+')&&!isdigit(tmpMsg[last_pos-1]))
        {
            return false;
        }
        if(tmpMsg[first_pos]=='-'||tmpMsg[first_pos]=='+')
        {
            if(first_pos==0)
            {
                opPos=tmpMsg.find_first_of(opStr,first_pos+1);
            }
            else{
                opPos=first_pos;
            }
        }
        else{
            if(first_pos==0)
            {
                return false;
            }
            opPos=first_pos;
        }
        std::string left=tmpMsg.substr(0,opPos);
        std::string right=tmpMsg.substr(0,opPos+1);
        req->set_X(atoi(left.c_str()));
        req->set_y(atoi(right.c_str()));
        req->set_op(tmpMsg[opPos]);

        req->debug();
        return true;
}